﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CollectionComparerUnitTests.cs" company="" />
//
// <summary>
//   Unit tests for the 'CollectionComparer'.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace UtilityUnitTests
{
    using System;
    using System.Collections.Generic;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using Utilities;

    /// <summary>
    /// Unit tests for the 'CollectionComparer'.
    /// </summary>
    [TestClass]
    public class CollectionComparerUnitTests
    {
        #region Constants

        private const int c_key1 = 1;
        private const int c_key2 = 2;
        private const int c_keyCommon = 3;
        private const string c_element1 = "a";
        private const string c_element2 = "b";
        private const string c_elementCommon = "c";

        #endregion

        /// <summary>
        /// Test the situation where the target collection is empty.
        /// </summary>
        [TestMethod]
        public void TargetCollectionEmptyTest()
        {
            var original = new Dictionary<int, string> { { c_key1, c_element1 } };
            var target = new Dictionary<int, string>();
            var comparer = new CollectionComparer<int, string>(original, target);

            // Verify contents of the only-original collection:
            Assert.AreEqual(1, comparer.OnlyOriginal.Count, "Only-original items count");
            Assert.IsTrue(comparer.OnlyOriginal.ContainsKey(c_key1), "Only-original collection is expected to contain item keyed '1'");
            Assert.AreEqual(c_element1, comparer.OnlyOriginal[c_key1], "Only-original collection is expected to contain item <1, a>");

            // Verify contents of the only-target collection:
            Assert.AreEqual(0, comparer.OnlyTarget.Count, "Only-target items count");

            // Verify contents of the differences collection:
            Assert.AreEqual(0, comparer.Differences.Count, "Differences items count");
        }

        /// <summary>
        /// Test the situation where the original collection is empty.
        /// </summary>
        [TestMethod]
        public void OriginalCollectionEmptyTest()
        {
            var original = new Dictionary<int, string>();
            var target = new Dictionary<int, string> { { c_key1, c_element1 } };
            var comparer = new CollectionComparer<int, string>(original, target);

            // Verify contents of the only-target collection:
            Assert.AreEqual(1, comparer.OnlyTarget.Count, "Only-target items count");
            Assert.IsTrue(comparer.OnlyTarget.ContainsKey(c_key1), "Only-target collection is expected to contain item keyed '1'");
            Assert.AreEqual(c_element1, comparer.OnlyTarget[c_key1], "Only-target collection is expected to contain item <1, a>");

            // Verify contents of the only-target collection:
            Assert.AreEqual(0, comparer.OnlyOriginal.Count, "Only-original items count");

            // Verify contents of the differences collection:
            Assert.AreEqual(0, comparer.Differences.Count, "Differences items count");
        }

        /// <summary>
        /// Test the situation where both the original and the target collections are empty.
        /// </summary>
        [TestMethod]
        public void BothCollectionsEmptyTest()
        {
            var original = new Dictionary<int, string>();
            var target = new Dictionary<int, string>();
            var comparer = new CollectionComparer<int, string>(original, target);

            Assert.AreEqual(0, comparer.OnlyOriginal.Count, "Only-original items count");
            Assert.AreEqual(0, comparer.OnlyTarget.Count, "Only-target items count");
            Assert.AreEqual(0, comparer.Differences.Count, "Differences itmes count");
        }

        /// <summary>
        /// Test the situation where original and target data-set are orthogonal.
        /// </summary>
        [TestMethod]
        public void OriginalAndTargetDataSetOrthogonalTest()
        {
            var original = new Dictionary<int, string> { { c_key1, c_element1 } };
            var target = new Dictionary<int, string> { { c_key2, c_element2 } };
            var comparer = new CollectionComparer<int, string>(original, target);

            // Verify contents of the only-original collection:
            Assert.AreEqual(1, comparer.OnlyOriginal.Count, "Only-original items count");
            Assert.IsTrue(comparer.OnlyOriginal.ContainsKey(c_key1), "Only-original collection is expected to contain item keyed '1'");
            Assert.AreEqual(c_element1, comparer.OnlyOriginal[c_key1], "Only-original collection is expected to contain item <1, a>");

            // Verify contents of the only-target collection:
            Assert.AreEqual(1, comparer.OnlyTarget.Count, "Only-target items count");
            Assert.IsTrue(comparer.OnlyTarget.ContainsKey(c_key2), "Only-target collection is expected to contain item keyed '2'");
            Assert.AreEqual(c_element2, comparer.OnlyTarget[c_key2], "Only-target collection is expected to contain item <2, b>");

            // Verify contents of the differences collection:
            Assert.AreEqual(0, comparer.Differences.Count, "Differences items count");
        }

        /// <summary>
        /// Test the situation where the original and target have equal data in common.
        /// </summary>
        [TestMethod]
        public void OriginalAndTargetEqualCommonDataTest()
        {
            var original = new Dictionary<int, string> { { c_key1, c_element1 }, { c_keyCommon, c_elementCommon } };
            var target = new Dictionary<int, string> { { c_key2, c_element2 }, { c_keyCommon, c_elementCommon } };
            var comparer = new CollectionComparer<int, string>(original, target);

            // Verify contents of the only-original collection:
            Assert.AreEqual(1, comparer.OnlyOriginal.Count, "Only-original items count");
            Assert.IsTrue(comparer.OnlyOriginal.ContainsKey(c_key1), "Only-original collection is expected to contain item keyed '1'");
            Assert.AreEqual(c_element1, comparer.OnlyOriginal[c_key1], "Only-original collection is expected to contain item <1, a>");

            // Verify contents of the only-target collection:
            Assert.AreEqual(1, comparer.OnlyTarget.Count, "Only-target items count");
            Assert.IsTrue(comparer.OnlyTarget.ContainsKey(c_key2), "Only-target collection is expected to contain item keyed '2'");
            Assert.AreEqual(c_element2, comparer.OnlyTarget[c_key2], "Only-target collection is expected to contain item <2, b>");

            // Verify contents of the differences collection:
            Assert.AreEqual(0, comparer.Differences.Count, "Differences items count");
        }

        /// <summary>
        /// Test the situation where the original and target have differences in common data.
        /// </summary>
        [TestMethod]
        public void OriginalAndTargetDiffCommonDataTest()
        {
            var original = new Dictionary<int, string> { { c_key1, c_element1 }, { c_keyCommon, c_element1 } };
            var target = new Dictionary<int, string> { { c_key2, c_element2 }, { c_keyCommon, c_element2 } };
            var comparer = new CollectionComparer<int, string>(original, target);

            // Verify contents of the only-original collection:
            Assert.AreEqual(1, comparer.OnlyOriginal.Count, "Only-original items count");
            Assert.IsTrue(comparer.OnlyOriginal.ContainsKey(c_key1), "Only-original collection is expected to contain item keyed '1'");
            Assert.AreEqual(c_element1, comparer.OnlyOriginal[c_key1], "Only-original collection is expected to contain item <1, a>");

            // Verify contents of the only-target collection:
            Assert.AreEqual(1, comparer.OnlyTarget.Count, "Only-target items count");
            Assert.IsTrue(comparer.OnlyTarget.ContainsKey(c_key2), "Only-target collection is expected to contain item keyed '2'");
            Assert.AreEqual(c_element2, comparer.OnlyTarget[c_key2], "Only-target collection is expected to contain item <2, b>");

            // Verify contents of the differences collection:
            Assert.AreEqual(1, comparer.Differences.Count, "Diffeneces items count");
            Assert.IsTrue(comparer.Differences.ContainsKey(c_keyCommon), "Differences collection is expected to contain item keyed '3'");
            Assert.AreEqual(
                new Tuple<string, string>(c_element1, c_element2),
                comparer.Differences[c_keyCommon],
                "Differences collection is expected to contain item <3, <a, b>>");
        }

        /// <summary>
        /// Test the situation where both the original and target collections contains the same information.
        /// </summary>
        [TestMethod]
        public void OriginalAndTargetTheSameTest()
        {
            var original = new Dictionary<int, string> { { c_key1, c_element1 } };
            var target = new Dictionary<int, string> { { c_key1, c_element1 } };
            var comparer = new CollectionComparer<int, string>(original, target);

            Assert.AreEqual(0, comparer.OnlyOriginal.Count, "Only-original collection count");
            Assert.AreEqual(0, comparer.OnlyTarget.Count, "Only-target collection count");
            Assert.AreEqual(0, comparer.Differences.Count, "Differences collection count");
        }
    }
}
